use crate::get;
use crate::Downloadable;
use model::asset::AssetIndex;
use model::asset::Index;
use parse::Parse;

// asset model is downloadable
impl Downloadable for AssetIndex {
  fn download(
    &self,
    game_dir: &std::path::Path,
  ) -> Result<(), Box<dyn std::error::Error>> {
    println!("Downloading asset index: {}", self.id);
    // <Minecraft Root Game Dir>/assets/indexes
    let indexes_dir = &game_dir.join("assets").join("indexes");
    if !indexes_dir.exists() {
      std::fs::create_dir_all(indexes_dir)?;
    }

    let config_json = &indexes_dir.join(&format!("{}.json", self.id)); // to create json file

    std::fs::File::create(config_json)?;

    let url_to_network_minecraft = &self.url;
    let text = &get(url_to_network_minecraft)?.text()?;

    std::fs::write(config_json, text)?;

    let index = Index::parse(text)?;

    let objects_dir = &game_dir.join("assets").join("objects");

    if !objects_dir.exists() {
      std::fs::create_dir_all(objects_dir)?;
    }

    for (_key, value) in index.objects {
      let hash = &value.hash;
      let hash_first_two = &hash[0..2];

      let first_two_dir = &objects_dir.join(hash_first_two);

      if !first_two_dir.exists() {
        std::fs::create_dir_all(first_two_dir)?;
      }

      let hashed_asset_file = &first_two_dir.join(hash);

      if hashed_asset_file.exists() {
        if crate::sha1(hashed_asset_file)?.eq(hash) {
          continue;
        } else {
          std::fs::remove_file(hashed_asset_file)?;
        }
      }

      std::fs::File::create(hashed_asset_file)?;

      let url = format!(
        "https://resources.download.minecraft.net/{}/{}",
        hash_first_two, hash
      );

      println!("Downloading asset: {}", hash);

      let bytes = get(&url)?.bytes()?;
      std::fs::write(hashed_asset_file, bytes)?;
    }

    Ok(())
  }
}
